#include "iap.h"
#include "stdio.h"
#include "ymodem.h"

uint8_t tab_1024[1024] = { 0 };
pFunction Jump_To_Application;

//跳转至APP
signed char IAP_RunApp(void)
{
    if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000) == 0x20000000)
    {
        printf("Run to app\n");
        unsigned int JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
        pFunction Jump_To_Application = (pFunction)JumpAddress;
        __set_MSP(*(__IO uint32_t*) ApplicationAddress);
        Jump_To_Application();
        return 0;
    }
    else
    {
        printf("\r\n Run to app error.\r\n");
        return -1;
    }
}

int8_t IAP_Update(void)
{
    int32_t Size = 0;
    Size = Ymodem_Receive(&tab_1024[0]);
    if (Size > 0)
    {
        printf("\r\n Update Over!\r\n");
        return 0;
    }
    else if (Size == -1)
    {
        printf("\r\n Image Too Big!\r\n");
        return -1;
    }
    else if (Size == -2)
    {
        printf("\r\n Update failed!\r\n");
        return -2;
    }
    else if (Size == -3)
    {
        printf("\r\n Aborted by user.\r\n");
        return -3;
    }
    else
    {
        printf(" Receive Filed.\r\n");
        return -4;
    }
}


//串口获取单个字符
uint32_t getSerialByte(uint8_t* key)
{

    if (USART_GetFlagStatus(IAP_USART, USART_FLAG_RXNE) != RESET)
    {
        *key = (uint8_t)IAP_USART->DR;
        return 1;
    }
    else
    {
        return 0;
    }
}

//串口获取字符串，最大128字节
void GetInputString(uint8_t* buffP)
{
    uint32_t bytes_read = 0;
    uint8_t c = 0;
    do
    {
        if (!getSerialByte(&c)) continue;
        if (c == '\n')
        {
            if (buffP[bytes_read - 1] == '\r')
                break;
        }

        if (c == '\b')
        {
            if (bytes_read > 0)
            {
                bytes_read--;
            }
            continue;
        }
        if (bytes_read >= 128)
        {
            printf("Cmd size out of range\n");
            bytes_read = 0;
            continue;
        }
        if ((c >= 0x20 && c <= 0x7E) || c == '\r')
        {
            buffP[bytes_read++] = c;
        }
    } while (1);

    buffP[bytes_read - 1] = '\0';
    printf("R:%s\n", buffP);
}


uint32_t FLASH_PagesMask(__IO uint32_t Size)
{
    uint32_t pagenumber = 0x0;
    uint32_t size = Size;

    if ((size % PAGE_SIZE) != 0)
    {
        pagenumber = (size / PAGE_SIZE) + 1;
    }
    else
    {
        pagenumber = size / PAGE_SIZE;
    }
    return pagenumber;
}

uint8_t EraseSomePages(__IO uint32_t size, uint8_t outPutCont)
{
    uint32_t EraseCounter = 0x0;
    uint32_t NbrOfPage = 0;
    char output_string[30];
    FLASH_Status FLASHStatus = FLASH_COMPLETE;

    NbrOfPage = FLASH_PagesMask(size);
	sprintf((char*)output_string, "page count:%d\n", NbrOfPage);
	SerialPutString(output_string);
	
    /* Erase the FLASH pages */
    FLASH_Unlock();
    for (EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
    {
        FLASHStatus = FLASH_ErasePage(ApplicationAddress + (PAGE_SIZE * EraseCounter));
        if (outPutCont == 1)
        {
            sprintf((char*)output_string, "page:%d\n", EraseCounter + 1);
            SerialPutString(output_string);
        }
    }
    FLASH_Lock();
    if ((EraseCounter != NbrOfPage) || (FLASHStatus != FLASH_COMPLETE))
    {
        return 0;
    }
    return 1;
}

int8_t IAP_Erase(void)
{

    if (EraseSomePages(FLASH_IMAGE_SIZE, 1))
        return 0;
    else
        return -1;
}

uint32_t SerialKeyPressed(uint8_t* key)
{

    if (USART_GetFlagStatus(IAP_USART, USART_FLAG_RXNE) != RESET)
    {
        *key = (uint8_t)IAP_USART->DR;
        return 1;
    }
    else
    {
        return 0;
    }
}
